package org.bookie.facebook.components;

import java.util.List;

import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.annotations.InjectState;
import org.bookie.framework.CommonBaseComponent;
import org.bookie.model.Bet;
import org.bookie.model.BetSlip;
import org.bookie.model.Category;
import org.bookie.model.Event;
import org.bookie.model.Outcome;
import org.bookie.model.Wager;
import org.bookie.model.Event.State;
import org.bookie.model.services.CategoryDAO;
import org.bookie.model.services.EventDAO;
import org.bookie.model.services.OutcomeDAO;

/**
 * Component for showing the events inside one category
 * 
 * @author zubairov
 */
public abstract class EventsList extends CommonBaseComponent {

	/**
	 * Injected service
	 * 
	 * @return
	 */
	@InjectObject("service:bookie.model.EventDAO")
	public abstract EventDAO getEventDAO();
	
	/**
	 * Injected service
	 * 
	 * @return
	 */
	@InjectObject("service:bookie.model.CategoryDAO")
	public abstract CategoryDAO getCategoryDAO();

	/**
	 * Injected service
	 * 
	 * @return
	 */
	@InjectObject("service:bookie.model.OutcomeDAO")
	public abstract OutcomeDAO getOutcomeDAO();
	
	/**
	 * Get injected {@link BetSlip}
	 */
	@InjectState("betSlip")
	public abstract BetSlip getBetSlip();
	
	/**
	 * Getter for the component parameter
	 */
	public abstract Long getCategoryID();
	
	/**
	 * Returns a selected {@link Category}
	 * @return
	 */
	public Category getCategory() {
		return getCategoryDAO().findById(getCategoryID());
	}
	
	/**
	 * Returns a collection of {@link Event} instances
	 * 
	 * @return
	 */
	public List<Event> getEvents() {
		return getEventDAO().findByCategory(getCategoryID());
	}

	/**
	 * Method called when user clicks on the link with outcome
	 * 
	 * @param outcomeId
	 */
	public void doBet(long outcomeId) {
		Outcome outcome = getOutcomeDAO().findById(outcomeId);
		if (outcome != null) {
			if(!isValid(outcome))return;
			if(alreadyExists(outcome))return;
			getBetSlip().addBet(new Wager(outcome));
		}
	}

	/**
	 * Returns true in case given {@link #getBetSlip()} already contain
	 * a {@link Wager} with given {@link Bet}
	 * 
	 * @param bet
	 * @return
	 */
	private boolean alreadyExists(Outcome outcome) {
		List<Wager> wagers = getBetSlip().getBets();
		for (Wager wager : wagers) {
			if (wager.getOutcome().getId().equals(outcome.getId())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns true wherever {@link Outcome} is valid
	 * 
	 * @param outcome
	 * @return
	 */
	private boolean isValid(Outcome outcome) {
        Bet bet = outcome.getBet();
        if(bet.getSuccessfulOutcome()!=null)
            return false;
        if(!bet.getEvent().getState().equals( State.ACTIVE))
            return false;
        return true;
	}
}
